/*
 * MPEGGranule.h
 *        -- define granule format for MPEG frame
 *
 * Author: Qiu Shuang
 * Date: Mar 2nd, 2011
 */
#ifndef MPEGGRANULE_H
#define MPEGGRANULE_H

#include <stdio.h>
#include "metadata.h"

/* forward declaration */
class MPEGFrameHeader;
class MPEGSideInfo;
class MPEGFrameData;

class MPEGGranule{
public:
    /* constructor */
    MPEGGranule(FILE *mpeg, MPEGFrameHeader *header, MPEGSideInfo *sideinfo, MPEGFrameData *scalefactor, int granule);

    /* destructor */
    ~MPEGGranule();

    /* set huffman decoded sample values */
    void setHuffmanSample(unsigned int value, int channel, int subband, int sub_index);

    /* get de-huffmaned samples for specified channel */
    ChannelDataLong *getDeHuffmanSamples(int channel);

    /* get restored huffman samples for specified channel */
    ChannelDataDouble *getRestoredSamples(int channel);

    /* get subband MDCT coefficients for specified channel */
    ChannelDataDouble *getMDCTCoefficients(int channel);

    /* get restored samples which is data we will manipulate */
    //ChannelDataDouble *getReorderedSamples(int channel);

    /* get window aligned samples */
    //double *getAlignedSamples(int channel);

    /* restore subband samples from huffman decoded samples */
    bool restoreSamples(int channel);

    /* decode joint stereo to MDCT coefficient */
    bool decodeJointStereo();

    /* reorder stereo decoded samples */
    //void reorder(int channel);

    /* align window size */
    //void align(int channel);

private:
    MPEGFrameHeader *_frame_header; /* get fundamental encoding information */
    MPEGSideInfo *_sideinfo;        /* get fundamental encoding information */
    MPEGFrameData *_scalefactor;    /* scale factor for the frame */
    int _granule_no;                /* number of this granule */

    ChannelDataLong _dehuffman_samples[CHANNEL];
    ChannelDataDouble _restored_samples[CHANNEL];
    ChannelDataDouble _mdct_coefficients[CHANNEL];
    //ChannelDataDouble _reordered_samples[CHANNEL];

                                    /* for window size alignment */
    //double _aligned_samples[CHANNEL][ALIGNED_SAMPLES];
};

/* set huffman decoded samples */
inline void MPEGGranule::setHuffmanSample(unsigned int value, int channel, int subband, int sub_index){
    _dehuffman_samples[channel][subband][sub_index] = value;
}

/* get de-huffmaned samples */
inline ChannelDataLong *MPEGGranule::getDeHuffmanSamples(int channel){
    return &(_dehuffman_samples[channel]);
}

/* get reordered huffman-decoded samples */
inline ChannelDataDouble *MPEGGranule::getRestoredSamples(int channel){
    return &(_restored_samples[channel]);
}

/* get subband MDCT coefficeint, samples are joint-stereo decoded */
inline ChannelDataDouble *MPEGGranule::getMDCTCoefficients(int channel){
    return &(_mdct_coefficients[channel]);
}

/* get reordered samples */
//inline ChannelDataDouble *MPEGGranule::getReorderedSamples(int channel){
//    return &(_reordered_samples[channel]);
//}

#endif